package com.cloudeggtech.granite.sdk;

import android.os.Handler;

import com.cloudeggtech.basalt.protocol.oxm.IOxmFactory;
import com.cloudeggtech.chalk.AbstractChatClient;
import com.cloudeggtech.chalk.AuthFailureException;
import com.cloudeggtech.chalk.core.stream.IAuthenticationCallback;
import com.cloudeggtech.chalk.core.stream.IAuthenticationFailure;
import com.cloudeggtech.chalk.core.stream.IStandardStreamer;
import com.cloudeggtech.chalk.core.stream.IStreamer;
import com.cloudeggtech.chalk.core.stream.StandardStreamConfig;
import com.cloudeggtech.chalk.core.stream.StreamConfig;
import com.cloudeggtech.chalk.core.stream.UsernamePasswordToken;
import com.cloudeggtech.chalk.core.stream.negotiants.tls.IPeerCertificateTruster;
import com.cloudeggtech.chalk.network.ConnectionException;
import com.cloudeggtech.chalk.network.IConnectionListener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


/**
 * Created by david on 17/10/26.
 */

public class GIMManager extends AbstractChatClient implements IConnectionListener {
    private static final Logger logger = LoggerFactory.getLogger(GIMManager.class);

    private static GIMManager instance = null;
    private static Object LOCK = new Object();
    private IStandardStreamer standardStreamer;
    private AuthenticationFail authenticationFail;

    private GIMManager(StreamConfig streamConfig) {
        super(streamConfig);
//        this.addConnectionListener(new Print());
    }

    public static void init(StreamConfig config) {
        if (config.getHost() == null || "".equals(config.getHost())) {
            logger.error("empty host");
            throw new IllegalArgumentException("host config cannot be null");
        }
        if (config.getPort() == 0) {
            logger.error("empty port");
            throw new IllegalArgumentException("port config cannot be null");
        }
        synchronized (LOCK) {
            if (instance == null) {
                instance = new GIMManager(config);
            }
        }
    }

    public static GIMManager getInstance() {
        return instance;
    }

    public void login(final String identify, final String password, final GIMCallback callback) {
        authenticationFail = new AuthenticationFail(callback);
//        handler.post(new Runnable() {
//            @Override
//            public void run() {
        try {
            connect(new UsernamePasswordToken(identify, password));
            callback.success();
        } catch (ConnectionException e) {
            logger.error("connection failed.", e);
            callback.failure(e);
        } catch (AuthFailureException e) {
            logger.error("connection failed.", e);
        }
//            }
//        });
    }

    private static class AuthenticationFail implements IAuthenticationCallback {

        private GIMCallback callback;
        private Handler handler;

        public AuthenticationFail(GIMCallback callback) {
            this.callback = callback;
            handler = new Handler();
        }

        @Override
        public void failed(final IAuthenticationFailure failure) {
            if (callback != null) {
                callback.failure(new Exception(failure.getErrorCondition().name()));
            }

        }
    }

    @Override
    protected IStreamer createStreamer(StreamConfig streamConfig) {
        standardStreamer = new GIMStreamer((StandardStreamConfig) streamConfig);
        standardStreamer.setAuthenticationCallback(authenticationFail);
        standardStreamer.setConnectionListener(new Print());
        standardStreamer.setNegotiationListener(this);
        // always trust peer certificate
        standardStreamer.setPeerCertificateTruster(new IPeerCertificateTruster() {
            @Override
            public boolean accept(javax.security.cert.X509Certificate[] certificates) {
                return true;
            }

        });
//		}

        return standardStreamer;
    }

    @Override
    protected IOxmFactory createOxmFactory() {
        return super.createOxmFactory();
    }


    private String md5(String password, String mobile) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            String str = password + "{" + mobile + "}";
            md.update(str.getBytes());
            return new BigInteger(1, md.digest()).toString(16);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    private static class Print implements IConnectionListener {

        @Override
        public void occurred(ConnectionException exception) {

        }

        @Override
        public void received(String message) {
            logger.debug("<-\t" + message);

        }

        @Override
        public void sent(String message) {
            logger.debug("->\t" + message);

        }
    }
}
